package com.eastfair.security.formfield;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.eastfair.annotation.base.LanguageTypeEnum;
import com.eastfair.cache.redis.RedisOps;
import com.eastfair.config.api.FormFieldServiceFeign;
import com.eastfair.config.dto.FormFieldDTO;
import com.eastfair.config.vo.FormFieldVO;
import com.eastfair.config.vo.ObjectFormFieldDetailVO;
import com.eastfair.config.vo.ObjectFormFieldEditVO;
import com.eastfair.constant.*;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.code.ExceptionCode;
import com.eastfair.core.jackson.JsonUtil;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.core.utils.MapFlatUtil;
import com.eastfair.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Date:2022/3/7
 * Time:13:54
 *
 * @author zjn
 */
@Component
@Slf4j
public class ConvertByFormField {

    @Autowired
    private FormFieldServiceFeign formFieldServiceFeign;
    @Autowired
    private RedisOps redisOps;

    /**
     * 展商 展品 观众 VO对象转换为表单详情对象
     *
     * @param obj          语言转换完成后的VO对象
     * @param formFieldDTO 及使用主体
     * @param <T>
     * @return
     */
    public <T> R<List<ObjectFormFieldDetailVO>> objectConvertFormFieldDetailVO(T obj, FormFieldDTO formFieldDTO) {
        if (Objects.isNull(formFieldDTO) || StringUtils.isBlank(formFieldDTO.getSubjectType())
                || (Objects.isNull(formFieldDTO.getIsDetails()) && Objects.isNull(formFieldDTO.getIsPerfectInfo()))) {
            return R.fail(ExceptionCode.ERROR_NULL_PARAMS);
        }
        formFieldDTO.setIsPerfectInfo(null);
        formFieldDTO.setIsDetails(BusinessConstant.YES);
        List<FormFieldVO> formFieldVOS = getFormFieldCache(formFieldDTO);
        R<List<ObjectFormFieldEditVO>> editConvert = objectConvert(obj, formFieldVOS, false);
        if (editConvert.getIsSuccess()) {
            return R.success(ConvertUtil.convertList(editConvert.getData(), ObjectFormFieldDetailVO.class));
        } else {
            return R.fail(editConvert.getMsg());
        }
    }

    /**
     * 展商 展品 观众 VO对象转换为表单编辑对象
     *
     * @param obj          语言转换完成后的VO对象
     * @param formFieldDTO 及使用主体
     * @param <T>
     * @return
     */
    public <T> R<List<ObjectFormFieldEditVO>> objectConvertFormFieldEditVO(T obj, FormFieldDTO formFieldDTO) {
        if (Objects.isNull(formFieldDTO) || StringUtils.isBlank(formFieldDTO.getSubjectType())
                || (Objects.isNull(formFieldDTO.getIsDetails()) && Objects.isNull(formFieldDTO.getIsPerfectInfo()))) {
            return R.fail(ExceptionCode.ERROR_NULL_PARAMS);
        }
        formFieldDTO.setIsPerfectInfo(BusinessConstant.YES);
        formFieldDTO.setIsDetails(null);
        List<FormFieldVO> formFieldVOS = getFormFieldCache(formFieldDTO);

        return objectConvert(obj, formFieldVOS, true);
    }

    private <T> R<List<ObjectFormFieldEditVO>> objectConvert(T obj, List<FormFieldVO> formFieldVOS, Boolean isEdit) {
        // 对象扁平化处理
        Map<String, Object> objectMap = MapFlatUtil.beanToFlatMap(obj);
        // 获取顶级对象的类名
        String clName = obj.getClass().getSimpleName();
        String classNameSuffix = null;
        if (clName.toLowerCase().endsWith(BizConstant.VO)) {
            clName = clName.substring(0, clName.length() - BizConstant.VO.length());
            classNameSuffix = BizConstant.VO;
        }
        if (clName.toLowerCase().endsWith(BizConstant.DTO)) {
            clName = clName.substring(0, clName.length() - BizConstant.DTO.length());
            classNameSuffix = BizConstant.DTO;
        }

        List<ObjectFormFieldEditVO> result = new ArrayList<>();
        // 组装数据
        for (FormFieldVO formFieldVO : formFieldVOS) {
            ObjectFormFieldEditVO objectFormFieldEditVO = BeanUtil.copyProperties(formFieldVO, ObjectFormFieldEditVO.class);
            // 获取属性值
            AtomicReference<String> ObjectKey = new AtomicReference<>();
            if (StringUtils.isBlank(formFieldVO.getClassName())) {
                return R.fail(ExceptionCode.ERROR_FORM_FIELD_CLASS_NAME);
            }
            // 处理正常属性值
            if (formFieldVO.getClassName().equalsIgnoreCase(clName)) {
                ObjectKey.set(formFieldVO.getKeyword());
            } else {
                String endStrObjectKey;
                if (StringUtils.isBlank(classNameSuffix)) {
                    endStrObjectKey = formFieldVO.getClassName() + StringConstant.SEPARATOR + formFieldVO.getKeyword();
                } else {
                    endStrObjectKey = formFieldVO.getClassName() + classNameSuffix + StringConstant.SEPARATOR + formFieldVO.getKeyword();
                }
                objectMap.keySet().forEach(key -> {
                    if (key.toLowerCase().endsWith(endStrObjectKey.toLowerCase())) {
                        ObjectKey.set(key);
                        return;
                    }
                });
            }
            if (!StringUtils.isBlank(ObjectKey.get())) {
                objectFormFieldEditVO.setObjectKey(ObjectKey.get());
                Object value = objectMap.get(ObjectKey.get());
                if (Objects.nonNull(value)) {
                    if (!StringUtils.isBlank(value.toString())) {
                        if (BusinessConstant.numberOne.equals(formFieldVO.getFieldTypeAttribute())) {
                            // 如果是字典，转为字符串
                            objectFormFieldEditVO.setValue(objectMap.get(ObjectKey.get()).toString());
                        } else {
                            objectFormFieldEditVO.setValue(objectMap.get(ObjectKey.get()));
                        }

                    }
                }

                // 处理前缀
                if (BusinessConstant.YES == formFieldVO.getIsPrefix()) {
                    if (formFieldVO.getClassName().equalsIgnoreCase(clName)) {
                        objectFormFieldEditVO.setPrefixObjectKey(formFieldVO.getPrefixKeyword());
                        objectFormFieldEditVO.setPrefixValue(objectMap.get(formFieldVO.getPrefixKeyword()));
                    } else {
                        String endStrObjectKey;
                        if (StringUtils.isBlank(classNameSuffix)) {
                            endStrObjectKey = formFieldVO.getClassName() + StringConstant.SEPARATOR + formFieldVO.getPrefixKeyword();
                        } else {
                            endStrObjectKey = formFieldVO.getClassName() + classNameSuffix + StringConstant.SEPARATOR + formFieldVO.getPrefixKeyword();
                        }
                        objectMap.keySet().forEach(key -> {
                            if (key.toLowerCase().endsWith(endStrObjectKey.toLowerCase())) {
                                objectFormFieldEditVO.setPrefixObjectKey(key);
                                if (!StringUtils.isBlank(objectMap.get(ObjectKey.get()).toString())) {
                                    objectFormFieldEditVO.setPrefixValue(objectMap.get(key));
                                }
                                return;
                            }
                        });
                    }
                }

                // 处理后缀
                if (BusinessConstant.YES == formFieldVO.getIsSuffix()) {
                    if (formFieldVO.getClassName().equalsIgnoreCase(clName)) {
                        objectFormFieldEditVO.setSuffixObjectKey(formFieldVO.getSuffixKeyword());
                        objectFormFieldEditVO.setSuffixValue(objectMap.get(formFieldVO.getSuffixKeyword()));
                    } else {
                        String endStrObjectKey;
                        if (StringUtils.isBlank(classNameSuffix)) {
                            endStrObjectKey = formFieldVO.getClassName() + StringConstant.SEPARATOR + formFieldVO.getSuffixKeyword();
                        } else {
                            endStrObjectKey = formFieldVO.getClassName() + classNameSuffix + StringConstant.SEPARATOR + formFieldVO.getSuffixKeyword();
                        }
                        objectMap.keySet().forEach(key -> {
                            if (key.toLowerCase().endsWith(endStrObjectKey.toLowerCase())) {
                                objectFormFieldEditVO.setSuffixObjectKey(key);
                                if (!StringUtils.isBlank(objectMap.get(ObjectKey.get()).toString())) {
                                    objectFormFieldEditVO.setSuffixValue(objectMap.get(key));
                                }
                                return;
                            }
                        });
                    }
                }
            }
            result.add(objectFormFieldEditVO);
        }

        if (isEdit) {
            /**
             * 特殊处理id
             * 目前是以id结尾的字段全部放入
             */
            objectMap.forEach((key, value) -> {
                if (key.equalsIgnoreCase(EntityAttributeString.ID)
                        || key.toLowerCase().endsWith(StringConstant.SEPARATOR + EntityAttributeString.ID)) {
                    ObjectFormFieldEditVO objectFormFieldEditVO = new ObjectFormFieldEditVO();
                    objectFormFieldEditVO.setObjectKey(key);
                    objectFormFieldEditVO.setValue(value);
                    result.add(objectFormFieldEditVO);
                }
            });
        }
        return R.success(result);
    }

    /**
     * 表单配置列表转换为展商 展品 观众 VO对象
     *
     * @param objectFormFieldEditVOList
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> R<T> editFormFieldVOConvertObject(List<ObjectFormFieldEditVO> objectFormFieldEditVOList, Class<T> clazz) {
        return formFieldVOConvert(objectFormFieldEditVOList, clazz);
    }

    private <T> R<T> formFieldVOConvert(List<ObjectFormFieldEditVO> objectFormFieldDetailsVOList, Class<T> clazz) {
        if (CollectionUtil.isEmpty(objectFormFieldDetailsVOList)) {
            return R.success(null);
        }

        Map<String, Object> entityMap = new HashMap<>();
        objectFormFieldDetailsVOList.parallelStream().forEach(objectFormFieldDetailsVO -> {
            if (!Objects.isNull(objectFormFieldDetailsVO.getObjectKey())) {
                entityMap.put(objectFormFieldDetailsVO.getObjectKey(), objectFormFieldDetailsVO.getValue());
            }
            // 处理前缀
            if (!Objects.isNull(objectFormFieldDetailsVO.getIsPrefix())
                    && BusinessConstant.YES == objectFormFieldDetailsVO.getIsPrefix()
                    && !Objects.isNull(objectFormFieldDetailsVO.getPrefixObjectKey())) {
                entityMap.put(objectFormFieldDetailsVO.getPrefixObjectKey(), objectFormFieldDetailsVO.getPrefixValue());
            }

            // 处理后缀
            if (!Objects.isNull(objectFormFieldDetailsVO.getIsSuffix())
                    && BusinessConstant.YES == objectFormFieldDetailsVO.getIsSuffix()
                    && !Objects.isNull(objectFormFieldDetailsVO.getSuffixObjectKey())) {
                entityMap.put(objectFormFieldDetailsVO.getSuffixObjectKey(), objectFormFieldDetailsVO.getSuffixValue());
            }

        });
        return R.success((T) MapFlatUtil.mapToFlatBean(entityMap, clazz));
    }

    private List<FormFieldVO> getFormFieldCache(FormFieldDTO formFieldDTO) {
        String redisKey;
        if (Objects.nonNull(formFieldDTO.getIsPerfectInfo()) && BusinessConstant.YES == formFieldDTO.getIsPerfectInfo()) {
            redisKey = String.format(RedisKeyConstant.FORM_FIELD_PERFECT_INFO_REDIS_KEY, formFieldDTO.getSubjectType(),
                    LanguageTypeEnum.get(ContextUtil.getLanguageType()), ContextUtil.getProjectId(), ContextUtil.getExhibitionId());
        } else if (Objects.nonNull(formFieldDTO.getIsDetails()) && BusinessConstant.YES == formFieldDTO.getIsDetails()) {
            redisKey = String.format(RedisKeyConstant.FORM_FIELD_DETAIL_REDIS_KEY, formFieldDTO.getSubjectType(),
                    LanguageTypeEnum.get(ContextUtil.getLanguageType()), ContextUtil.getProjectId(), ContextUtil.getExhibitionId());
        } else {
            throw new IllegalStateException("未知的表单类型");
        }
        String formFieldStr = redisOps.get(redisKey);
        if (StringUtils.isBlank(formFieldStr)) {
            // 获取表单配置
            formFieldDTO.setExhibitionId(ContextUtil.getExhibitionId());
            formFieldDTO.setLanguageType(ContextUtil.getLanguageType());
            formFieldDTO.setIsEnabled(BusinessConstant.ENABLE_YES);
            formFieldDTO.setProjectId(ContextUtil.getProjectId());
            formFieldDTO.setIsPerfectInfo(formFieldDTO.getIsPerfectInfo());
            formFieldDTO.setIsDetails(formFieldDTO.getIsDetails());
            List<FormFieldVO> formFieldVOS = formFieldServiceFeign.getBySubjectType(formFieldDTO).getData();
            if (CollectionUtil.isNotEmpty(formFieldVOS)) {
                if (LanguageTypeEnum.EN.eq(ContextUtil.getLanguageType())) {
                    formFieldVOS = (List<FormFieldVO>) ConvertUtil.convertByLanguageType(formFieldVOS, LanguageTypeEnum.EN, true);
                }
                redisOps.set(redisKey, JsonUtil.toJson(formFieldVOS), false);
                redisOps.expire(redisKey, 24 * 60 * 60);
            }
            return formFieldVOS;
        }
        return JsonUtil.parseArray(formFieldStr, FormFieldVO.class);
    }

}
